package com.anpy.security.service;

import com.anpy.security.entity.Platform;
import com.anpy.security.entity.Role;
import com.anpy.security.entity.User;
import com.anpy.security.repository.PlatformRepository;
import com.anpy.security.repository.RoleRepository;
import com.anpy.security.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PlatformRepository platformRepository;
    
    @Autowired
    private RoleRepository roleRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    /**
     * Get all users for a specific platform
     * 
     * @param platformCode The platform code
     * @return List of users for the platform
     */
    public List<User> getAllUsersByPlatform(String platformCode) {
        Platform platform = getPlatformByCode(platformCode);
        return userRepository.findByPlatform(platform);
    }
    
    /**
     * Get user by ID and platform
     * 
     * @param id The user ID
     * @param platformCode The platform code
     * @return The user if found
     */
    public User getUserById(Long id, String platformCode) {
        Platform platform = getPlatformByCode(platformCode);
        return userRepository.findById(id)
                .filter(user -> user.getPlatform().getId().equals(platform.getId()))
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id + " in platform: " + platformCode));
    }
    
    /**
     * Create a new user in a specific platform
     * 
     * @param user The user to create
     * @param platformCode The platform code
     * @return The created user
     */
    @Transactional
    public User createUser(User user, String platformCode) {
        Platform platform = getPlatformByCode(platformCode);
        
        // Check if username already exists in this platform
        if (userRepository.existsByUsernameAndPlatform(user.getUsername(), platform)) {
            throw new RuntimeException("Username already exists in platform: " + platformCode);
        }
        
        // Set platform and encode password
        user.setPlatform(platform);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        
        return userRepository.save(user);
    }
    
    /**
     * Update an existing user
     * 
     * @param id The user ID
     * @param userDetails The updated user details
     * @param platformCode The platform code
     * @return The updated user
     */
    @Transactional
    public User updateUser(Long id, User userDetails, String platformCode) {
        Platform platform = getPlatformByCode(platformCode);
        
        User user = userRepository.findById(id)
                .filter(u -> u.getPlatform().getId().equals(platform.getId()))
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id + " in platform: " + platformCode));
        
        // Update user details
        user.setEmail(userDetails.getEmail());
        user.setFullName(userDetails.getFullName());
        user.setEnabled(userDetails.isEnabled());
        
        // Update password if provided
        if (userDetails.getPassword() != null && !userDetails.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(userDetails.getPassword()));
        }
        
        // Update roles if provided
        if (userDetails.getRoles() != null && !userDetails.getRoles().isEmpty()) {
            user.setRoles(userDetails.getRoles());
        }
        
        return userRepository.save(user);
    }
    
    /**
     * Delete a user
     * 
     * @param id The user ID
     * @param platformCode The platform code
     */
    @Transactional
    public void deleteUser(Long id, String platformCode) {
        Platform platform = getPlatformByCode(platformCode);
        
        User user = userRepository.findById(id)
                .filter(u -> u.getPlatform().getId().equals(platform.getId()))
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id + " in platform: " + platformCode));
        
        userRepository.delete(user);
    }
    
    /**
     * 获取用户的所有角色
     * 
     * @param userId 用户ID
     * @param platformCode 平台代码
     * @return 角色列表
     */
    public List<Role> getUserRoles(Long userId, String platformCode) {
        User user = getUserById(userId, platformCode);
        return new ArrayList<>(user.getRoles());
    }
    
    /**
     * 为用户分配角色
     * 
     * @param userId 用户ID
     * @param roleId 角色ID
     * @param platformCode 平台代码
     * @return 更新后的用户
     */
    @Transactional
    public User assignRoleToUser(Long userId, Long roleId, String platformCode) {
        User user = getUserById(userId, platformCode);
        Platform platform = getPlatformByCode(platformCode);
        
        Role role = roleRepository.findById(roleId)
                .filter(r -> r.getPlatform().getId().equals(platform.getId()))
                .orElseThrow(() -> new RuntimeException("Role not found with id: " + roleId + " in platform: " + platformCode));
        
        // 添加角色到用户
        user.getRoles().add(role);
        return userRepository.save(user);
    }
    
    /**
     * 从用户移除角色
     * 
     * @param userId 用户ID
     * @param roleId 角色ID
     * @param platformCode 平台代码
     * @return 更新后的用户
     */
    @Transactional
    public User removeRoleFromUser(Long userId, Long roleId, String platformCode) {
        User user = getUserById(userId, platformCode);
        Platform platform = getPlatformByCode(platformCode);
        
        Role role = roleRepository.findById(roleId)
                .filter(r -> r.getPlatform().getId().equals(platform.getId()))
                .orElseThrow(() -> new RuntimeException("Role not found with id: " + roleId + " in platform: " + platformCode));
        
        // 从用户移除角色
        user.getRoles().remove(role);
        return userRepository.save(user);
    }
    
    /**
     * 批量更新用户角色
     * 
     * @param userId 用户ID
     * @param roleIds 角色ID列表
     * @param platformCode 平台代码
     * @return 更新后的用户
     */
    @Transactional
    public User updateUserRoles(Long userId, List<Long> roleIds, String platformCode) {
        User user = getUserById(userId, platformCode);
        Platform platform = getPlatformByCode(platformCode);
        
        // 清空当前角色
        user.getRoles().clear();
        
        // 添加新角色
        if (roleIds != null && !roleIds.isEmpty()) {
            Set<Role> roles = new HashSet<>();
            for (Long roleId : roleIds) {
                Role role = roleRepository.findById(roleId)
                        .filter(r -> r.getPlatform().getId().equals(platform.getId()))
                        .orElseThrow(() -> new RuntimeException("Role not found with id: " + roleId + " in platform: " + platformCode));
                roles.add(role);
            }
            user.setRoles(roles);
        }
        
        return userRepository.save(user);
    }
    
    /**
     * Helper method to get platform by code
     * 
     * @param platformCode The platform code
     * @return The platform
     */
    private Platform getPlatformByCode(String platformCode) {
        return platformRepository.findByCode(platformCode)
                .orElseThrow(() -> new RuntimeException("Platform not found: " + platformCode));
    }
}
